package com.shanzmoo.core.manager;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.Assert;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.shanzmoo.base.bean.PageRespBase;
import com.shanzmoo.base.bean.SResponse;
import com.shanzmoo.base.exception.OutletOrderException;
import com.shanzmoo.core.cache.CurrentUserCache;
import com.shanzmoo.core.constant.FactoryOrderStatus;
import com.shanzmoo.core.constant.OutletOrderStatusConstant;
import com.shanzmoo.core.domain.FactoryOrderSaveDto;
import com.shanzmoo.db.order.entity.OutletOrderDetailEntity;
import com.shanzmoo.db.order.entity.OutletOrderEntity;
import com.shanzmoo.db.order.service.IOutletOrderDetailService;
import com.shanzmoo.db.order.service.IOutletOrderService;
import com.shanzmoo.db.produce.entity.FactoryOrderDetailEntity;
import com.shanzmoo.db.produce.entity.FactoryOrderEntity;
import com.shanzmoo.db.produce.entity.dto.FactoryOrderDeatailSaveDto;
import com.shanzmoo.db.produce.entity.dto.FactoryOrderQueryDto;
import com.shanzmoo.db.produce.entity.vo.FactoryOrderDetailVo;
import com.shanzmoo.db.produce.entity.vo.FactoryOrderPageVo;
import com.shanzmoo.db.produce.service.IFactoryOrderDetailService;
import com.shanzmoo.db.produce.service.IFactoryOrderService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 *
 *
 * @author： Gzhao 2021/1/31
 */
@Slf4j
@Component
public class FactoryOrderMananger {

    @Autowired
    private IFactoryOrderService factoryOrderService;
    @Autowired
    private IFactoryOrderDetailService factoryOrderDetailService;
    @Autowired
    private IOutletOrderService outletOrderService;
    @Autowired
    private IOutletOrderDetailService outletOrderDetailService;
    @Autowired
    private OutletOrderLogManager outletOrderLogManager;
    @Autowired
    private OutletOrderManager outletOrderManager;

    @Transactional(rollbackFor = Exception.class)
    public void saveOrder(FactoryOrderSaveDto saveDto, Integer memberId) {
        List<FactoryOrderSaveDto.FactoryOrderGroup> groupList = saveDto.getGroupList();
        for (FactoryOrderSaveDto.FactoryOrderGroup group : groupList) {

            FactoryOrderEntity factoryOrderEntity = group.convert(saveDto.getOrderNo(), memberId);
            factoryOrderService.save(factoryOrderEntity);

            List<FactoryOrderDetailEntity> detailList = FactoryOrderDeatailSaveDto.createList(group.getDeatailList(),
                    factoryOrderEntity.getProductionNo());
            factoryOrderDetailService.saveBatch(detailList);
        }


    }

    public SResponse<PageRespBase<FactoryOrderPageVo>> getPageList(FactoryOrderQueryDto queryDto) {
        Page page = PageHelper.startPage(queryDto.getPageNum(), queryDto.getPageSize());

        List<FactoryOrderPageVo> reList = factoryOrderService.selectPageInfo(queryDto);

        PageRespBase<FactoryOrderPageVo> re = PageRespBase.create(page, reList);
        PageHelper.clearPage();
        return SResponse.ok(re);
    }

    public SResponse<List<FactoryOrderDetailVo>> details(String productionNo) {
        FactoryOrderEntity factoryOrder = obtainSelfOrderByNo(productionNo);

        List<FactoryOrderDetailEntity> list = factoryOrderDetailService.list(
                new QueryWrapper<FactoryOrderDetailEntity>()
                        .eq("deleted", false)
                        .eq("production_no", factoryOrder.getProductionNo())
        );

        List<FactoryOrderDetailVo> reList = FactoryOrderDetailVo.createList(list);
        return SResponse.ok(reList);
    }

    @Transactional(rollbackFor = Exception.class)
    public SResponse<Boolean> finish(String productionNo) {
        FactoryOrderEntity factoryOrder = obtainSelfOrderByNo(productionNo);
        if (factoryOrder.getStatus() != FactoryOrderStatus.DOING) {
            throw new OutletOrderException("请选择“生产中”订单");
        }
        FactoryOrderEntity updateOrder = FactoryOrderEntity.builder()
                .id(factoryOrder.getId())
                .status(FactoryOrderStatus.FINISH)
                .finishTime(LocalDateTime.now())
                .finishUser(CurrentUserCache.getUserId())
                .build();
        factoryOrderService.updateById(updateOrder);

        updateOutletOrderStatus(factoryOrder);

        return SResponse.ok(Boolean.TRUE);
    }

    @Transactional(rollbackFor = Exception.class)
    public SResponse<Boolean> cancel(String productionNo) {
        FactoryOrderEntity factoryOrder = obtainSelfOrderByNo(productionNo);
        if (factoryOrder.getStatus() != FactoryOrderStatus.DOING) {
            throw new OutletOrderException("请选择“生产中”订单");
        }

        FactoryOrderEntity factoryOrderUpdate = FactoryOrderEntity.builder()
                .id(factoryOrder.getId())
                .updateUser(CurrentUserCache.getUserId())
                .deleted(true)
                .build();
        factoryOrderService.updateById(factoryOrderUpdate);

        // 若订单没有生产单了，更新订单状态
        OutletOrderEntity outletOrder = outletOrderManager.obtainSelfOrderByNo(factoryOrder.getOrderNo());
        Assert.isFalse(outletOrder != null, "未获取到原始订单信息");

        outletOrderLogManager.saveLog(outletOrder.getId(), "取消分配单：" + factoryOrder.getProductionNo());

        List<FactoryOrderEntity> factoryOrderList = factoryOrderService.list(
                new QueryWrapper<FactoryOrderEntity>()
                        .eq("deleted", false)
                        .eq("order_no", outletOrder.getOrderNo())
        );
        if (CollectionUtil.isEmpty(factoryOrderList)) {
            OutletOrderEntity outletOrderUpdate = OutletOrderEntity.builder()
                    .id(outletOrder.getId())
                    .status(OutletOrderStatusConstant.NEW)
                    .updateUser(CurrentUserCache.getUserId())
                    .build();
            outletOrderService.updateById(outletOrderUpdate);
        }
        return SResponse.ok(Boolean.TRUE);
    }

    public void checkSkuNumByOrder(String orderNo) {
        // 订单刷机商品明细
        List<OutletOrderDetailEntity> outletOrderDetailList = outletOrderDetailService.list(
                new QueryWrapper<OutletOrderDetailEntity>()
                        .eq("deleted", false)
                        .eq("root", true)
                        .eq("order_no", orderNo)
        );

        // 生产单
        List<FactoryOrderEntity> factoryOrderList = factoryOrderService.list(
                new QueryWrapper<FactoryOrderEntity>()
                        .eq("deleted", false)
                        .eq("order_no", orderNo)
        );

        // 生产单明细
        List<String> productionNoList = factoryOrderList.stream().map(FactoryOrderEntity::getProductionNo).collect(Collectors.toList());
        List<FactoryOrderDetailEntity> factoryOrderDetailList = factoryOrderDetailService.list(
                new QueryWrapper<FactoryOrderDetailEntity>()
                        .eq("deleted", false)
                        .in("production_no", productionNoList)
        );

        // 对 sku分组求和
        Map<String, Integer> factoryOrderSkuMap = factoryOrderDetailList.stream()
                .collect(Collectors.groupingBy(e -> e.getSku(), Collectors.summingInt(FactoryOrderDetailEntity::getSkuNum)));
        Map<String, Integer> outletOrderSkuMap = outletOrderDetailList.stream()
                .collect(Collectors.groupingBy(e -> e.getSku(), Collectors.summingInt(OutletOrderDetailEntity::getSkuNum)));

        // 对比 sku 数量
        for (String sku : factoryOrderSkuMap.keySet()){
            Integer outletOrderSkuNum = outletOrderSkuMap.get(sku);
            if (outletOrderSkuMap == null){
                throw new OutletOrderException("原始订单：" + orderNo + "，商品明细中未查询到 sku：" + sku);
            }
            Integer factoryOrderSkuNum = factoryOrderSkuMap.get(sku);
            if (factoryOrderSkuNum > outletOrderSkuNum){
                throw new OutletOrderException("商品 sku：" + sku  + ", 分配后的合计数量是 " + factoryOrderSkuNum
                        + ", 超过原始订单的商品数量 " + outletOrderSkuNum );
            }
        }
    }

    /**
     * 生产单完成，若订单所有的生产单都完成，则更新订单的状态
     *
     * @param factoryOrder
     */
    private void updateOutletOrderStatus(FactoryOrderEntity factoryOrder) {
        OutletOrderEntity outletOrder = outletOrderManager.obtainSelfOrderByNo(factoryOrder.getOrderNo());
        if (outletOrder == null) {
            return;
        }

        outletOrderLogManager.saveLog(outletOrder.getId(), "完成分配单：" + factoryOrder.getProductionNo());
        // 生产单
        List<FactoryOrderEntity> factoryOrderList = factoryOrderService.list(
                new QueryWrapper<FactoryOrderEntity>()
                        .eq("deleted", false)
                        .eq("order_no", outletOrder.getOrderNo())
        );
        for (FactoryOrderEntity factoryOrderEntity : factoryOrderList) {
            if (factoryOrderEntity.getStatus() == FactoryOrderStatus.DOING) {
                return;
            }
        }

        /**
         * 若生产单都已生产完成，再对比订单刷机sku数量是否一致
         */
        // 生产单明细
        List<String> productionNoList = factoryOrderList.stream().map(FactoryOrderEntity::getProductionNo).collect(Collectors.toList());
        List<FactoryOrderDetailEntity> factoryOrderDetailList = factoryOrderDetailService.list(
                new QueryWrapper<FactoryOrderDetailEntity>()
                        .eq("deleted", false)
                        .in("production_no", productionNoList)
        );
        // 对 sku分组求和
        Map<String, Integer> factoryOrderMap = factoryOrderDetailList.stream()
                .collect(Collectors.groupingBy(e -> e.getSku(), Collectors.summingInt(FactoryOrderDetailEntity::getSkuNum)));

        // 订单刷机商品明细
        List<OutletOrderDetailEntity> outletOrderDetailList = outletOrderDetailService.list(
                new QueryWrapper<OutletOrderDetailEntity>()
                        .eq("deleted", false)
                        .eq("root", true)
                        .eq("order_no", outletOrder.getOrderNo())
        );
        Map<String, Integer> outletOrderMap = outletOrderDetailList.stream()
                .collect(Collectors.groupingBy(e -> e.getSku(), Collectors.summingInt(OutletOrderDetailEntity::getSkuNum)));

        // sku 数量不一致，订单未分配完成
        if (factoryOrderMap.size() != outletOrderMap.size()) {
            return;
        }

        // 对比sku数量
        for (String sku : factoryOrderMap.keySet()) {
            if (!factoryOrderMap.get(sku).equals(outletOrderMap.get(sku))) {
                return;
            }
        }

        // 修改订单状态已完成
        OutletOrderEntity outletOrderUpdate = OutletOrderEntity.builder()
                .id(outletOrder.getId())
                .status(OutletOrderStatusConstant.WAIT_TAKE)
                .updateUser(CurrentUserCache.getUserId())
                .build();
        outletOrderService.updateById(outletOrderUpdate);

    }

    private FactoryOrderEntity obtainSelfOrderByNo(String productionNo) {
        FactoryOrderEntity order = factoryOrderService.getOne(
                new QueryWrapper<FactoryOrderEntity>()
                        .eq("deleted", false)
                        .eq("production_no", productionNo)
                        .eq("outlet_id", CurrentUserCache.getOutletId())
        );
        if (order == null) {
            throw new OutletOrderException("请输入正确的生产单号");
        }
        return order;
    }

}
